#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>

#define SEP " "
#define SEP_LEN strlen(SEP)
#define LINE_SEP "\r\n"
#define LINE_SEP_LEN strlen(LINE_SEP)
#define NUM 1024

//请求结构化数据
class Request
{
public:
    Request()
    {}
    Request(int x_, int y_, char op_)
        :x(x_)
        ,y(y_)
        ,op(op_)
    {}

    //序列化  "x + y"
    bool serialize(std::string *out)
    {
#ifdef MYSELF
        std::string x_string = std::to_string(x);
        std::string y_string = std::to_string(y);
        if(x_string.empty() || y_string.empty()) return false;
        *out = x_string;
        *out += SEP;
        *out += op;
        *out += SEP;
        *out += y_string;
#else 
        Json::Value root;
        root["left"] = x;
        root["right"] = y;
        root["op"] = op;
        
        Json::FastWriter writer;
        *out = writer.write(root);

#endif

        return true;
    }


    //反序列化 "x + y" 
    bool deserialize(const std::string &in)
    {
#ifdef MYSELF

        size_t left = in.find(SEP);
        size_t right = in.rfind(SEP);

        if(left == std::string::npos || right == std::string::npos) return false;
            
        if(left == right) return false;

        if(right - left - SEP_LEN != 1) return false;

        std::string x_string = in.substr(0, left);
        x = std::stoi(x_string);
        op = in.substr(left + SEP_LEN, 1)[0];
        std::string y_string = in.substr(right + SEP_LEN);
        y = std::stoi(y_string);   
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        x = root["left"].asInt();
        y = root["right"].asInt();
        op = root["op"].asInt();
        

#endif   
        return true;
    }
public:
    int x;
    int y;
    char op;
};

//响应结构化数据
class Response
{
public:
    Response()
    {}
    Response(int exitcode_, int result_)
        :exitcode(exitcode_)
        ,result(result_)
    {}

    //序列化 "exitcode result"
    bool serialize(std::string *out)
    {
#ifdef MYSELF
        std::string exitcode_string = std::to_string(exitcode);
        std::string result_string = std::to_string(result);   
        if(exitcode_string.empty() || result_string.empty()) return false;
        *out = exitcode_string;
        *out += SEP;
        *out += result_string;
#else
        Json::Value root;
        root["exitcode"] = exitcode;
        root["result"] = result;
        Json::StyledWriter writer;
        *out = writer.write(root);
        
#endif
        return true;

    }
    //反序列化  "exitcode result"
    bool deserialize(const std::string &in)
    {
#ifdef MYSELF
        size_t pos = in.find(SEP);
        if(pos == std::string::npos) return false;
        std::string exitcode_string = in.substr(0, pos);
        exitcode = std::stoi(exitcode_string);
        std::string result_string = in.substr(pos + SEP_LEN);
        result = std::stoi(result_string);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);

        exitcode = root["exitcode"].asInt();
        result = root["result"].asInt();
        
#endif
        return true;
    }
public:
    int exitcode;
    int result;
};


//   "text_len"\r\n"context"\r\n
bool recvPackage(int sock, std::string &inbuffer, std::string *out)
{
    char buffer[NUM];
    while(true)
    {
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if(n > 0) buffer[n] = 0;
        else return false;

        inbuffer += buffer;
        std::cout << "处理前inbuffer:\n " << inbuffer << std::endl;
        size_t pos = inbuffer.find(LINE_SEP);
        if(pos == std::string::npos) return false;
        std::string text_len_string = inbuffer.substr(0, pos);
        int text_len = std::stoi(text_len_string);
        
        int packagelen = text_len_string.size() + text_len + 2 * LINE_SEP_LEN;
        if(inbuffer.size() < packagelen)
            continue;
        *out = inbuffer.substr(0, packagelen);
        inbuffer.erase(0, packagelen);
        std::cout << "处理后inbuffer:\n " << inbuffer << std::endl;

        return true;
    }
}


//去掉报头
//"text_len"\r\n"text"\r\n -> text
bool deLenth(const std::string &package, std::string &text)
{
    size_t pos = package.find(LINE_SEP);
    if(pos == std::string::npos) return false;

    std::string text_len_string = package.substr(0, pos);
    int text_len = std::stoi(text_len_string);

    text = package.substr(pos + LINE_SEP_LEN, text_len);
    return true;

}

//添加报文
bool enLenth(const std::string &text, std::string &package)
{
    int text_len = text.size();
    package = std::to_string(text_len);
    package += LINE_SEP;
    package += text;
    package += LINE_SEP;
    return true;
}